package com.baselibrary.livedata;

import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.Observer;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zhanglijie
 * @date 2020/4/1
 * 事件总线
 */
public class LiveDataBus {
    private static final String DEFAULT_KEY = "LiveData:";

    private static class Lazy {
        static LiveDataBus sLiveDataBus = new LiveDataBus();
    }

    public static LiveDataBus get() {
        return Lazy.sLiveDataBus;
    }

    /**
     * 存放订阅者
     */
    private final ConcurrentHashMap<String, BusMutiableLiveData> mHashMap = new ConcurrentHashMap<>();

    public <T> BusMutiableLiveData<T> remove(String key) {
        if (mHashMap.contains(key)) {
            return mHashMap.remove(key);
        }
        return null;
    }

    public void removeObserver() {
        if (mHashMap != null) {
            mHashMap.clear();
        }
    }

    public <T> BusMutiableLiveData<T> with(String key, Class<T> type) {
        String realKey = getRealKey(key, type);
        if (!mHashMap.containsKey(realKey)) {
            mHashMap.put(realKey, new BusMutiableLiveData<Object>());
        }
        BusMutiableLiveData liveData = mHashMap.get(realKey);
        return (BusMutiableLiveData<T>) liveData;
    }


    private <T> String getRealKey(String key, Class<T> type) {
        if (type == null) {
            return DEFAULT_KEY + key;
        } else {
            return DEFAULT_KEY + key + type.getCanonicalName();
        }
    }

    public static class BusMutiableLiveData<T> extends MutableLiveData<T> {
        private int mVersion = 0;

        private BusMutiableLiveData() {
        }

        @Override
        public void setValue(T value) {
            mVersion++;
            super.setValue(value);
        }

        @Override
        public void postValue(T value) {
            mVersion++;
            super.postValue(value);
        }

        @Override
        public void observe(@androidx.annotation.NonNull LifecycleOwner owner,
                            @androidx.annotation.NonNull Observer observer) {
//            super.observe(owner, observer);
//            hook(observer);
            super.observe(owner, new WrapperObserver<>(this, observer));
        }

        /**
         * 粘性订阅
         */
        public void observeSticky(LifecycleOwner owner, Observer observer) {
            super.observe(owner, observer);
        }

        private void hook(Observer<? super T> observer) {
            try {
                //1.得到mLastVersion
                Class<androidx.lifecycle.LiveData> liveDataClass = androidx.lifecycle.LiveData.class;
                Field mObserversFeild = liveDataClass.getDeclaredField("mObservers");
                mObserversFeild.setAccessible(true);
                //获取到这个成员变量的对象
                Object mObserversObject = mObserversFeild.get(this);
                //得到map对应的class对象
                Class<?> mObserversClass = mObserversObject.getClass();
                //需要执行get方法
                Method get = mObserversClass.getDeclaredMethod("get", Object.class);
                get.setAccessible(true);
                Object invokeEntry = get.invoke(mObserversObject, observer);

                Object observerWraper = null;

                if (invokeEntry != null && invokeEntry instanceof Map.Entry) {
                    observerWraper = ((Map.Entry) invokeEntry).getValue();
                }
                if (observerWraper == null) {
                    throw new NullPointerException("observerWraper is null!");
                }
                //得到ObserveWraper的类对象 ,编译擦除问题
                Class<?> superclass = observerWraper.getClass().getSuperclass();
                Field mLastVersion = superclass.getDeclaredField("mLastVersion");
                mLastVersion.setAccessible(true);
                Object o = mLastVersion.get(observerWraper);
                //2.得到mVersion
                Field mVersion = liveDataClass.getDeclaredField("mVersion");
                mVersion.setAccessible(true);
                //3.mLastVersion填到mVersion中
                Object mVersionValue = mVersion.get(this);
                mLastVersion.set(observerWraper, mVersionValue);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static class WrapperObserver<T> implements Observer<T> {
        private final BusMutiableLiveData mLiveData;
        private final Observer<? super T> mObserver;

        //标记该liveData已经发射几次数据了，用以过滤老数据重复接收
        private int mLastVersion = 0;

        private WrapperObserver(BusMutiableLiveData liveData, Observer observer) {
            mLiveData = liveData;
            mObserver = observer;
            mLastVersion = mLiveData.mVersion;
        }

        @Override
        public void onChanged(T t) {
            if (mLastVersion < mLiveData.mVersion) {
                mLastVersion = mLiveData.mVersion;
                mObserver.onChanged(t);
            }
        }
    }
}
